use super::*;

impl IntoNapi for () {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		env.null()
	}
}
impl IntoNapi for bool {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		let mut ptr = core::ptr::null_mut();
		unsafe { sys::napi_get_boolean(env.raw(), self, &mut ptr) }
			.result("napi_create_uint32")
			.map(|_| Value::new(env, ptr))
	}
}
impl IntoNapi for u32 {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		let mut ptr = core::ptr::null_mut();
		unsafe { sys::napi_create_uint32(env.raw(), self, &mut ptr) }
			.result("napi_create_uint32")
			.map(|_| Value::new(env, ptr))
	}
}
impl IntoNapi for i32 {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		let mut ptr = core::ptr::null_mut();
		unsafe { sys::napi_create_int32(env.raw(), self, &mut ptr) }
			.result("napi_create_int32")
			.map(|_| Value::new(env, ptr))
	}
}
impl IntoNapi for i64 {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		let mut ptr = core::ptr::null_mut();
		unsafe { sys::napi_create_int64(env.raw(), self, &mut ptr) }
			.result("napi_create_int64")
			.map(|_| Value::new(env, ptr))
	}
}
impl IntoNapi for f64 {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		let mut ptr = core::ptr::null_mut();
		unsafe { sys::napi_create_double(env.raw(), self, &mut ptr) }
			.result("napi_create_double")
			.map(|_| Value::new(env, ptr))
	}
}
impl<'c> IntoNapi for &'c str {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		let mut ptr = core::ptr::null_mut();
		unsafe { sys::napi_create_string_utf8(env.raw(), self.as_ptr() as _, self.len(), &mut ptr) }
			.result("napi_create_string_utf8")
			.map(|_| Value::new(env, ptr))
	}
}
impl IntoNapi for String {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		self.as_str().into_napi(env)
	}
}
impl IntoNapi for &String {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		self.as_str().into_napi(env)
	}
}
impl<'c> IntoNapi for &'c core::ffi::CStr {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		let mut ptr = core::ptr::null_mut();
		unsafe { sys::napi_create_string_utf8(env.raw(), self.as_ptr(), self.count_bytes(), &mut ptr) }
			.result("napi_create_string_utf8")
			.map(|_| Value::new(env, ptr))
	}
}
impl IntoNapi for std::ffi::CString {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		self.as_c_str().into_napi(env)
	}
}
impl IntoNapi for &std::ffi::CString {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		self.as_c_str().into_napi(env)
	}
}
impl<T: IntoNapi> IntoNapi for Option<T> {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		match self {
			Some(v) => v.into_napi(env),
			None => env.null(),
		}
	}
}
impl<T: IntoNapi, E: IntoNapi> IntoNapi for core::result::Result<T, E> {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		match self {
			Ok(value) => value.into_napi(env),
			Err(error) => error.into_napi(env),
		}
	}
}

// converted

impl IntoNapi for u8 {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		(self as u32).into_napi(env)
	}
}

impl IntoNapi for u16 {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		(self as u32).into_napi(env)
	}
}

impl IntoNapi for u64 {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		(self as f64).into_napi(env)
	}
}

impl IntoNapi for i8 {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		(self as i32).into_napi(env)
	}
}

impl IntoNapi for i16 {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		(self as i32).into_napi(env)
	}
}

impl IntoNapi for f32 {
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		(self as f64).into_napi(env)
	}
}
